package com.itheima.jdk;

import com.itheima.jdk.Advice;
import com.itheima.jdk.Target;
import com.itheima.jdk.TargetInterface;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Target(目标对象):代理的目标对象
 * Proxy(代理): 一个类被aop织入增强后,产生代理类
 * Joinpoint(连接点): 可以被拦截到的点.在spring中指的是方法类型的连接点
 * Pointcut(切入点): 指我们要对哪些joinpoint进行拦截.也就是我们关心的joinpoint
 * Advice(通知/增强): 在pointcut上所做的事
 * Aspect(切面): 是切点+增强
 * Weaving(织入): 把增强应用到目标对象来创建新的代理对象的过程,spring采用动态代理织入,而aspectj采用编译期织入和类装载期织入
 */
public class ProxyTest {
    //aop基于动态代理实现
    /*
     * 常用的动态代理技术
     * 1 JDK代理:基于接口的动态代理技术
     * 2 cglib代理:基于父类的动态代理技术
     * */

    public static void main(String[] args) {
        jdkProxy();

    }

    /**
     * 基于jdk的依托于接口的代理 示例
     * 这是基本原理,spring会进行封装,让你方便的使用动态代理技术,进行aop编程
     */
    private static void jdkProxy() {
        //目标对象 被代理对象
        final Target target = new Target();
        //增强对象
        final Advice advice = new Advice();
        //返回值 动态生成的代理对象
        TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader() //目标对象的类加载器
                , target.getClass().getInterfaces() //目标对象的接口
                , new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //前置增强
                        advice.before();
                        Object invoke = method.invoke(target, args);//执行目标方法
                        //后置增强
                        advice.after();
                        return invoke;
                    }
                });
        //调用生成的代理的方法
        proxy.save();
    }

}
